﻿using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;
using System.Windows.Navigation;
using TheVerge.Phone.Controls;

namespace TheVerge.Phone.Pages
{
    public abstract class BasePage : PhoneApplicationPage
    {
        private AppBarState AppBar;

        public BasePage()
        {
            var bar = new ApplicationBar();
            bar.IsVisible = false;
            ApplicationBar = bar;
            TiltEffect.SetIsTiltEnabled(this, true);

            SetupNavigationTransitions();
        }

        public void LoadBar()
        {
            AppBarHelper.Load(Buttons, MenuItems, IsMini);
            ConfigureButtons();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            if (AppBar != null)
                AppBarHelper.Load(AppBar);
            else
                LoadBar();

            ForceOrientation();

            ConfigureButtons();
            LoadFromQueryStrings(CreateQueryStrings(e.Uri.ToString()));
        }

        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            base.OnNavigatingFrom(e);
            AppBar = AppBarHelper.CurrentAppBar;
        }

        #region BasePage
        protected abstract bool IsMini { get; }
        protected abstract IEnumerable<IApplicationBarIconButton> Buttons { get; }
        protected abstract IEnumerable<IApplicationBarMenuItem> MenuItems { get; }

        protected virtual void ConfigureButtons() { }

        protected virtual void LoadFromQueryStrings(Dictionary<string, string> queryStrings) { }

        /// <summary>
        /// When overridden in a derviced class, sets the supported orientation of the page. By
        /// default we retrieve the supported orientation from the active theme.
        /// </summary>
        protected virtual SupportedPageOrientation OverridePageOrientation() { return Theme.Active.SupportedOrientation; }
        #endregion

        private static Dictionary<string, string> CreateQueryStrings(string uri)
        {
            var dic = new Dictionary<string, string>();

            if (string.IsNullOrEmpty(uri))
                return dic;

            var queryIdx = uri.IndexOf('?');
            if (queryIdx < 0)
                return dic;

            var query = uri.Substring(queryIdx + 1);

            var pairs = query.Split(new string[] { @"&" }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var p in pairs)
            {
                var key_val = p.Split('=');
                dic[key_val[0]] = key_val[1];
            }

            return dic;
        }

        #region Orientation Locking
        private bool ChangeSupportedOrientation;
        private SupportedPageOrientation SupportedOrientationAfterChange;

        private void ForceOrientation()
        {
            var supported = OverridePageOrientation();

            if (supported == SupportedPageOrientation.Portrait)
            {
                switch (Orientation)
                {
                    case PageOrientation.Landscape:
                    case PageOrientation.LandscapeLeft:
                    case PageOrientation.LandscapeRight:
                    case PageOrientation.None:
                        OrientationChanged += BasePage_OrientationChanged;
                        ChangeSupportedOrientation = true;
                        SupportedOrientationAfterChange = supported;
                        SupportedOrientations = SupportedPageOrientation.PortraitOrLandscape;
                        return;
                    default:
                        break;
                }
            }
            else if (supported == SupportedPageOrientation.Landscape)
            {
                switch (Orientation)
                {
                    case PageOrientation.None:
                    case PageOrientation.Portrait:
                    case PageOrientation.PortraitDown:
                    case PageOrientation.PortraitUp:
                        Orientation = PageOrientation.Landscape;
                        break;
                    default:
                        break;
                }
            }

            SupportedOrientations = supported;
        }

        private void BasePage_OrientationChanged(object sender, OrientationChangedEventArgs e)
        {
            if (ChangeSupportedOrientation)
            {
                SupportedOrientations = SupportedOrientationAfterChange;
                ChangeSupportedOrientation = false;
                OrientationChanged -= BasePage_OrientationChanged;
            }
        } 
        #endregion

        private void SetupNavigationTransitions()
        {
            NavigationInTransition navigateInTransition = new NavigationInTransition();
            navigateInTransition.Backward = new SlideTransition { Mode = SlideTransitionMode.SlideRightFadeIn };
            navigateInTransition.Forward = new SlideTransition { Mode = SlideTransitionMode.SlideLeftFadeIn };

            NavigationOutTransition navigateOutTransition = new NavigationOutTransition();
            navigateOutTransition.Backward = new SlideTransition { Mode = SlideTransitionMode.SlideRightFadeOut };
            navigateOutTransition.Forward = new SlideTransition { Mode = SlideTransitionMode.SlideLeftFadeOut };
            TransitionService.SetNavigationInTransition(this, navigateInTransition);
            TransitionService.SetNavigationOutTransition(this, navigateOutTransition);
        }
    }
}
